package junior.util.io;

import junior.util.exception.ExceptionUtils;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.List;

/**
 * @author WuBo
 * @CreateDate 2013-11-19 上午11:12:34
 */
public class FileUtils {
    
    public static void writeFile(File file, String content, Charset charset) {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(file);
            IOUtils.writeContent(os, content, charset);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            Closer.close(os);
        }
    }
    
    public static void writeFile(String filePath, String content, Charset charset) {
        writeFile(new File(filePath), content, charset);
    }
    
    public static String getFileContent(File file, Charset charset) {
        FileInputStream is = null;
        try {
            is = new FileInputStream(file);
            return IOUtils.getContent(is, charset);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            Closer.close(is);
        }
    }

	public static String getFileContent(String filePath, Charset charset) {
        return getFileContent(new File(filePath), charset);
	}
	
	public static List<String> getAllLines(String filePath, Charset charset) {
		FileInputStream is = null;
		try {
			is = new FileInputStream(filePath);
			return IOUtils.getAllLines(is, charset);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			Closer.close(is);
		}
	}
	
	public static String getFilename(String filePath) {
		String filename = filePath;
		
		int lastIndex = filePath.lastIndexOf("\\");
		if(lastIndex == -1) {
			lastIndex = filePath.lastIndexOf("/");
		}
		if(lastIndex != -1) {
			filename = filePath.substring(lastIndex + 1);
		}
		return filename;
	}
	/**
	 * 得到去掉路径的文件名，不包含扩展名
	 * @author WuBo
	 * @CreateDate 2013-11-19 上午11:26:43
	 * @param filePath
	 * @return
	 */
	public static String getFilenameWithoutExtName(String filePath) {
		String filename = getFilename(filePath);
		
		int idx = filename.lastIndexOf(".");
		if (idx != -1) {
			return filename.substring(0, idx);
		}
		return filename;
	}
	/**
	 * 得到文件扩展名
	 * @param fileName
	 * @return
	 */
	public static String getFileExtName(String fileName) {
		int idx = fileName.lastIndexOf(".");
		if (idx != -1) {
			return fileName.substring(idx + 1);
		}
		return "";
	}

	/**
	 * 创建目录
	 * @param dir
	 */
	public static void mkdir(File dir){
		if(dir.exists()) return;
		File parent = getParentFile(dir);
		if(parent != null) {
			if(! parent.exists()) {
				mkdir(parent);
			}
		}
		int tryTimes = 3;
		boolean exists = false;
		while(! (exists = dir.mkdirs())){
			if(--tryTimes < 0){
				break;
			}
		}
		if(! exists){
			throw new RuntimeException("无法创建文件："+dir.getPath());
		}
	}
	public static String getParent(String path) {
		if(path.indexOf("\\") != -1) {
			return path.substring(0, path.lastIndexOf("\\"));
		} else if(path.indexOf("/") != -1) {
			return path.substring(0, path.lastIndexOf("/"));
		}
		throw new RuntimeException("无法得到父路径");
	}
	/**
	 * 得到文件目录的父级目录路径
	 * @param dir
	 * @return
	 */
	public static String getParent(File dir) {
		if(dir.exists()) return dir.getParent();
		
		String path = switchPathSeparator(dir.getAbsolutePath());
		return new File(path).getParent();
	}
	/**
	 * 得到文件目录的父级目录
	 * @param dir
	 * @return
	 */
	public static File getParentFile(File dir) {
		if(dir.exists()) return dir.getParentFile();
		
		String path = switchPathSeparator(dir.getAbsolutePath());
		return new File(path).getParentFile();
	}
	
	/**
	 * 删除文件
	 * @param file
	 */
	public static void delete(File file){
		if(! file.exists()) return;
		int tryTimes = 3;
		boolean del = false;
		while(! (del = file.delete())){
			if(--tryTimes < 0){
				break;
			}
		}
		if(! del){
			if(file.canWrite()){
				throw new RuntimeException("无法删除文件："+file.getAbsolutePath()+"，可能文件正在被使用");
			}
			throw new RuntimeException("无法删除文件："+file.getAbsolutePath());
		}
	}
	/**
	 * 删除文件
	 * @param file
	 * @param delDir 是否删除目录（如果文件是一个目录）
	 */
	public static void delete(File file, boolean delDir) {
		if(file.isDirectory()) {
			 if(! delDir) {
				return;
			 }
			 for(File f : file.listFiles()) {
				 delete(f, delDir);
			 }
		}
		delete(file);
	}
	
	public static void pipeStream(InputStream is, OutputStream os) {
		try {
		    byte[] data = new byte[40960];
		    int len = 0;
		    while((len = is.read(data)) != -1) {
		    	os.write(data, 0, len);
		    }
		    os.flush();
		}catch(Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 复制文件
	 * @param source
	 * @param target
	 */
	public static void copy(File source, File target) {
		try {
			copy(new FileInputStream(source), new FileOutputStream(target));
		} catch (Exception e) {
			throw ExceptionUtils.wrap2Runtime(e);
		}
	}
	/**
	 * 复制文件
	 * @param fis
	 * @param fos
	 */
	public static void copy(FileInputStream fis, FileOutputStream fos) {
		FileChannel in = null;
		FileChannel out = null;
		try {
			in = fis.getChannel();
			out = fos.getChannel();
			
			// magic number for Windows, 64Mb - 32Kb)
		    int maxCount = (64 * 1024 * 1024) - (32 * 1024);
		    long size = in.size();
		    long position = 0;
		    while (position < size) {
		    	position += in.transferTo(position, maxCount, out);
		    }
		} catch (Exception e) {
			throw ExceptionUtils.wrap2Runtime(e);
		} finally {
			if(in != null) {try{in.close();}catch(Exception e){}}
			if(out != null) {try{out.close();}catch(Exception e){}}
			if(fis != null) {try{fis.close();}catch(Exception e){}}
			if(fos != null) {try{fos.close();}catch(Exception e){}}
		}
	}
	/**
	 * 返回指定文件的大小，如果是一个目录，则返回目录中所有文件的总大小
	 * @param dir
	 * @return
	 */
	public static long length(File dir) {
		if(dir.isDirectory()) {
			long total = 0;
			for(File file : dir.listFiles()) {
				total += length(file);
			}
			return total;
		}
		return dir.length();
	}
	
	/**
	 * 将文件分隔符转换成当前系统路径分隔符
	 * @param path
	 * @return
	 */
	public static String switchPathSeparator(String path){
		char separator = File.separatorChar;
		
		String pathSeparator = separator == '\\' ? separator+"\\" : separator+"";
		
		return path.replaceAll("[/\\\\]", pathSeparator);
	}

	/**
	 * 为文件路径加上路径分隔符前缀
	 * @param path
	 * @return
	 */
	public static String appendSperatorPrefix(String path){
		if(! path.startsWith("\\") && ! path.startsWith("/")){
			if(path.indexOf("\\") != -1){
				return "\\" + path;
			}else{
				return "/" + path;
			}
		}
		return path;
	}
	
	/**
	 * 为文件路径加上路径分隔符后缀
	 * @param path
	 * @return
	 */
	public static String appendSeparatorSuffix(String path){
		if(! path.endsWith("\\") && ! path.endsWith("/")){
			if(path.indexOf("\\") != -1){
				return path + "\\";
			}else{
				return path + "/";
			}
		}
		return path;
	}
	/**
	 * 去掉文件路径的分隔符前缀
	 * @param path
	 * @return
	 */
	public static String delSeparatorPrefix(String path) {
		if(path.startsWith("\\") || path.startsWith("/")) {
			return path.substring(1);
		}
		return path;
	}
	/**
	 * 去掉文件路径的分隔符后缀
	 * @param path
	 * @return
	 */
	public static String delSeparatorSuffix(String path) {
		if(path.endsWith("\\") || path.endsWith("/")) {
			return path.substring(0, path.length() - 1);
		}
		return path;
	}
}
